package com.castle.fortress.admin.flowable.controller;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.castle.fortress.admin.core.annotation.CastleLog;
import com.castle.fortress.admin.core.constants.GlobalConstants;
import com.castle.fortress.admin.flowable.dto.FlowableAppDto;
import com.castle.fortress.admin.flowable.dto.FlowableTemplateDto;
import com.castle.fortress.admin.flowable.enums.ApproveStatusEnum;
import com.castle.fortress.admin.flowable.form.entity.FlowableFormConfigEntity;
import com.castle.fortress.admin.flowable.form.service.FlowableFormConfigService;
import com.castle.fortress.admin.flowable.form.service.FlowableFormDataService;
import com.castle.fortress.admin.flowable.service.ApprovesService;
import com.castle.fortress.admin.flowable.service.FlowableManageService;
import com.castle.fortress.admin.form.dto.FormDataDto;
import com.castle.fortress.admin.form.service.FormModelService;
import com.castle.fortress.admin.system.entity.SysUser;
import com.castle.fortress.admin.utils.WebUtil;
import com.castle.fortress.common.entity.RespBody;
import com.castle.fortress.common.enums.OperationTypeEnum;
import com.castle.fortress.common.enums.YesNoEnum;
import com.castle.fortress.common.exception.BizException;
import com.castle.fortress.common.respcode.BizErrorCode;
import com.castle.fortress.common.respcode.GlobalRespCode;
import com.castle.fortress.common.utils.CommonUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

/**
 * 审批管理控制器
 *
 * @author castle
 * @since 2022-09-21
 */
@Api(tags="流程审批管理控制器")
@Controller
public class ApprovesController {
    @Autowired
    private ApprovesService approvesService;
    @Autowired
    private FlowableFormConfigService flowableFormConfigService;
    @Autowired
    private FormModelService formModelService;
    @Autowired
    private FlowableFormDataService flowableFormDataService;
    @Autowired
    private FlowableManageService flowableManageService;

    /**
     * 应用列表
     * @param current 当前页
     * @param size  每页记录数
     * @return
     */
    @CastleLog(operLocation = "应用列表分页展示", operType = OperationTypeEnum.QUERY)
    @ApiOperation("应用列表分页展示")
    @GetMapping("/flowable/approves/pageList")
    @ResponseBody
    public RespBody<IPage<FlowableAppDto>> pageFlowableApp(FlowableAppDto flowableAppDto, @RequestParam(required = false) Integer current, @RequestParam(required = false)Integer size){
        Integer pageIndex= current==null? GlobalConstants.DEFAULT_PAGE_INDEX:current;
        Integer pageSize= size==null? GlobalConstants.DEFAULT_PAGE_SIZE:size;
        Page<FlowableAppDto> page = new Page(pageIndex, pageSize);
        SysUser user = WebUtil.currentUser();
        IPage<FlowableAppDto> pages = approvesService.pageFlowableApp(page, flowableAppDto,user);
        return RespBody.data(pages);
    }

    /**
     * 发起审批流程
     * @param formDataDto 表模型
     * @return
     */
    @CastleLog(operLocation = "发起审批流程", operType = OperationTypeEnum.INSERT)
    @ApiOperation("发起审批流程")
    @PostMapping("/flowable/approves/saveData")
    @ResponseBody
    public RespBody<String> saveData(@RequestBody FormDataDto formDataDto, HttpServletRequest request){
        //非登陆用户不可发起申请
        SysUser user = WebUtil.currentUser();
        if(user==null){
            throw new BizException(GlobalRespCode.UNAUTHORIZED);
        }
        //审核状态为待审批
        formDataDto.getFormData().put("_castle_approve_status", ApproveStatusEnum.PENDING.getCode());
        if(CommonUtil.verifyParamNull(formDataDto,formDataDto.getTbId(),formDataDto.getFormData())){
            throw new BizException(GlobalRespCode.PARAM_MISSED);
        }
        FlowableFormConfigEntity configEntity = flowableFormConfigService.getById(formDataDto.getTbId());
        if(configEntity == null){
            throw new BizException(GlobalRespCode.UNAUTHORIZED);
        }
        //校验表名是否存在
        if(!formModelService.isExistTable("castle_approve_form"+formDataDto.getTbId())){
            throw new BizException(GlobalRespCode.UNAUTHORIZED);
        }
        //将表Id放入参数表中
        Map<String,Object> variables=new HashMap<>();
        //初始化发起人信息
        formDataDto.getFormData().put("_castle_apply_user",user.getId());
        formDataDto.getFormData().put("_castle_apply_date",new Date());
        formDataDto.getFormData().put("_castle_apply_dept",user.getDeptId());
        formDataDto.getFormData().put("_castle_apply_dept_parents",user.getDeptParents());
        formDataDto.getFormData().put("_castle_apply_post",user.getPostId());
        if(YesNoEnum.YES.getCode().equals(configEntity.getIsHoliday())){
            // 把请假类型  请假时长  放到variables 里,结束流程时省去查询
            JSONObject value = new JSONObject(formDataDto.getFormData().getOrDefault("fortress_holiday","{}"));
            variables.put("leaveType",value.get("type"));
            variables.put("leaveDuration",value.get("leaveDuration"));
        }
        flowableFormDataService.saveData(formDataDto.getTbId(),"castle_approve_form"+formDataDto.getTbId(),formDataDto.getFormData());
        variables.put("tid",formDataDto.getTbId());
        variables.put("id",formDataDto.getFormData().get("id")+"");
        flowableManageService.initFlowableVariables(user,variables,formDataDto);
        flowableManageService.runProcess(Long.parseLong(formDataDto.getTbId()),variables,user);
        return RespBody.data("保存成功");
    }

    /**
     * 数据详情
     * @param id 表单配置管理id
     * @return
     */
    @CastleLog(operLocation = "数据详情", operType = OperationTypeEnum.QUERY)
    @ApiOperation("数据详情")
    @GetMapping("/flowable/approves/info")
    @ResponseBody
    public RespBody<Map<String, Object>> infoData(@RequestParam String tbId, @RequestParam String id){
        if(CommonUtil.verifyParamNull(tbId,id)){
            throw new BizException(GlobalRespCode.PARAM_MISSED);
        }
        return RespBody.data(flowableFormDataService.queryById(tbId,id));
    }

    /**
     * 当前用户提交的任务列表
     * @param params
     * @return
     */
    @CastleLog(operLocation = "当前用户提交的任务列表", operType = OperationTypeEnum.QUERY)
    @ApiOperation("当前用户提交的任务列表")
    @GetMapping("/flowable/approves/myTasks")
    @ResponseBody
    public RespBody<IPage<Map<String,Object>>> myTasks(@RequestParam(required = false) Map<String,String> params){
        Integer current = Integer.parseInt(params.get("current"));
        Integer size = Integer.parseInt(params.get("size"));
        Integer pageIndex= current==null? GlobalConstants.DEFAULT_PAGE_INDEX:current;
        Integer pageSize= size==null? GlobalConstants.DEFAULT_PAGE_SIZE:size;
        Page<FlowableTemplateDto> page = new Page(pageIndex, pageSize);
        SysUser user = WebUtil.currentUser();
        IPage<Map<String,Object>> pages = flowableManageService.myTasks(page,user,params);
        return RespBody.data(pages);
    }

    /**
     * 当前用户代办任务列表分页展示
     * @param params
     * @return
     */
    @CastleLog(operLocation = "当前用户代办任务列表分页展示", operType = OperationTypeEnum.QUERY)
    @ApiOperation("当前用户代办任务列表分页展示")
    @GetMapping("/flowable/approves/todoTasks")
    @ResponseBody
    public RespBody<IPage<Map<String,Object>>> todoTasks(@RequestParam(required = false) Map<String,String> params){
        //非登陆用户不可发起申请
        SysUser user = WebUtil.currentUser();
        if(user==null){
            throw new BizException(GlobalRespCode.UNAUTHORIZED);
        }
        Integer current = Integer.parseInt(params.get("current"));
        Integer size = Integer.parseInt(params.get("size"));
        Integer pageIndex= current==null? GlobalConstants.DEFAULT_PAGE_INDEX:current;
        Integer pageSize= size==null? GlobalConstants.DEFAULT_PAGE_SIZE:size;
        Page<FlowableTemplateDto> page = new Page(pageIndex, pageSize);
        IPage<Map<String,Object>> pages = flowableManageService.todoTasks(page,user,params);
        return RespBody.data(pages);
    }

    /**
     * 当前用户参与的已完成任务列表分页展示
     * @param params
     * @return
     */
    @CastleLog(operLocation = "当前用户参与的已完成任务列表分页展示", operType = OperationTypeEnum.QUERY)
    @ApiOperation("当前用户参与的已完成任务列表分页展示")
    @GetMapping("/flowable/approves/finishTasks")
    @ResponseBody
    public RespBody<IPage<Map<String,Object>>> finishTasks(@RequestParam(required = false) Map<String,String> params){
        //非登陆用户不可发起申请
        SysUser user = WebUtil.currentUser();
        if(user==null){
            throw new BizException(GlobalRespCode.UNAUTHORIZED);
        }
        Integer current = Integer.parseInt(params.get("current"));
        Integer size = Integer.parseInt(params.get("size"));
        Integer pageIndex= current==null? GlobalConstants.DEFAULT_PAGE_INDEX:current;
        Integer pageSize= size==null? GlobalConstants.DEFAULT_PAGE_SIZE:size;
        Page<FlowableTemplateDto> page = new Page(pageIndex, pageSize);
        IPage<Map<String,Object>> pages = flowableManageService.finishTasks(page,user,params);
        return RespBody.data(pages);
    }

    /**
     * 通过/拒绝任务
     *
     * @param params
     * @return
     */
    @CastleLog(operLocation = "通过/拒绝任务", operType = OperationTypeEnum.INSERT)
    @PostMapping("/flowable/approves/completeTask")
    @ResponseBody
    public RespBody<String> completeTask(@RequestBody Map<String,String> params) {
        //非登陆用户不可发起申请
        SysUser user = WebUtil.currentUser();
        if(user==null){
            throw new BizException(GlobalRespCode.UNAUTHORIZED);
        }
        return RespBody.data(flowableManageService.completeTask(user,params));
    }

    /**
     * 取消任务
     *
     * @param params
     * @return
     */
    @CastleLog(operLocation = "取消任务", operType = OperationTypeEnum.INSERT)
    @PostMapping("/flowable/approves/cancelTask")
    @ResponseBody
    public RespBody<String> cancelTask(@RequestBody Map<String,String> params) {
        //非登陆用户不可发起申请
        SysUser user = WebUtil.currentUser();
        if(user==null){
            throw new BizException(GlobalRespCode.UNAUTHORIZED);
        }
        return RespBody.data(flowableManageService.cancelTask(user,params));
    }

    /**
     * 结束流程
     *
     * @param params
     * @return
     */
    @CastleLog(operLocation = "结束流程", operType = OperationTypeEnum.UPDATE)
    @PostMapping("/flowable/approves/endTask")
    @ResponseBody
    public RespBody<String> endTask(@RequestBody Map<String,String> params) {
        //非登陆用户不可发起申请
        SysUser user = WebUtil.currentUser();
        if(user==null){
            throw new BizException(GlobalRespCode.UNAUTHORIZED);
        }
        //pid流程实例Id
        if(CommonUtil.verifyParamNull(params,params.get("pid"),params.get("tid"),params.get("id"))){
            throw new BizException(GlobalRespCode.PARAM_MISSED);
        }
        return RespBody.data(flowableManageService.endProcess(params.get("pid"),params.get("tid"),params.get("id"),ApproveStatusEnum.ENDPRO.getCode()+""));
    }


    /**
     * 废弃
     * 流程历史节点
     * @param params
     * @return
     */
    @CastleLog(operLocation = "流程历史节点", operType = OperationTypeEnum.QUERY)
    @Deprecated
    @ApiOperation("流程历史节点")
    @GetMapping("/flowable/approves/historyNodes")
    @ResponseBody
    public RespBody<List<Map<String,Object>>> historyNodes(@RequestParam Map<String,String> params){
        //非登陆用户不可发起申请
        SysUser user = WebUtil.currentUser();
        if(user==null){
            throw new BizException(GlobalRespCode.UNAUTHORIZED);
        }
        List<Map<String,Object>> list = flowableManageService.historyNodes(user,params);
        return RespBody.data(list);
    }

    /**
     * 流程所有参与人
     * @param params
     * @return
     */
    @CastleLog(operLocation = "流程所有参与人", operType = OperationTypeEnum.QUERY)
    @ApiOperation("流程所有参与人")
    @GetMapping("/flowable/approves/allParticipants")
    @ResponseBody
    public RespBody<List<Map<String,Object>>> allParticipants(@RequestParam Map<String,String> params){
        //非登陆用户不可发起申请
        SysUser user = WebUtil.currentUser();
        if(user==null){
            throw new BizException(GlobalRespCode.UNAUTHORIZED);
        }
        List<Map<String,Object>> list = flowableManageService.allParticipants(user,params);
        return RespBody.data(list);
    }

    /**
     * 审批人自选抄送人
     * @param params
     * @return
     */
    @CastleLog(operLocation = "审批人自选抄送人", operType = OperationTypeEnum.INSERT)
    @ApiOperation("审批人自选抄送人")
    @GetMapping("/flowable/approves/csOptional")
    @ResponseBody
    public RespBody<Map<String,Object>> csOptional(@RequestParam Map<String,String> params){
        //非登陆用户不可发起申请
        SysUser user = WebUtil.currentUser();
        if(user==null){
            throw new BizException(GlobalRespCode.UNAUTHORIZED);
        }
        return RespBody.data(flowableManageService.csOptional(user,params));
    }


    /**
     * 抄送我任务列表分页展示
     * @param params
     * @return
     */
    @CastleLog(operLocation = "抄送我任务列表分页展示", operType = OperationTypeEnum.QUERY)
    @ApiOperation("抄送我任务列表分页展示")
    @GetMapping("/flowable/approves/csToMe")
    @ResponseBody
    public RespBody<IPage<Map<String,Object>>> csToMe(@RequestParam(required = false) Map<String,String> params){
        //非登陆用户不可发起申请
        SysUser user = WebUtil.currentUser();
        if(user==null){
            throw new BizException(GlobalRespCode.UNAUTHORIZED);
        }
        Integer current = Integer.parseInt(params.get("current"));
        Integer size = Integer.parseInt(params.get("size"));
        Integer pageIndex= current==null? GlobalConstants.DEFAULT_PAGE_INDEX:current;
        Integer pageSize= size==null? GlobalConstants.DEFAULT_PAGE_SIZE:size;
        Page<FlowableTemplateDto> page = new Page(pageIndex, pageSize);
        IPage<Map<String,Object>> pages = flowableManageService.csToMe(page,user,params);
        return RespBody.data(pages);
    }

    /**
     * 委派任务
     * 前加签
     * @param params
     * @return
     */
    @CastleLog(operLocation = "委派任务前加签", operType = OperationTypeEnum.INSERT)
    @PostMapping("/flowable/approves/delegateTask")
    @ResponseBody
    public RespBody<String> delegateTask(@RequestBody Map<String,String> params) {
        //非登陆用户不可发起申请
        SysUser user = WebUtil.currentUser();
        if(user==null){
            throw new BizException(GlobalRespCode.UNAUTHORIZED);
        }
        return RespBody.data(flowableManageService.delegateTask(user,params));
    }

    /**
     * 转办 转办一人
     * @param params
     * @return
     */
    @CastleLog(operLocation = "转办 转办一人", operType = OperationTypeEnum.UPDATE)
    @PostMapping("/flowable/approves/turnTask")
    @ResponseBody
    public RespBody<String> turnTask(@RequestBody Map<String,String> params) {
        //非登陆用户不可发起申请
        SysUser user = WebUtil.currentUser();
        if(user==null){
            throw new BizException(GlobalRespCode.UNAUTHORIZED);
        }
        return RespBody.data(flowableManageService.turnTask(user,params));
    }

    /**
     * 查询指定节点的回退方式
     * @param params
     * @return
     */
    @CastleLog(operLocation = "查询指定节点的回退方式", operType = OperationTypeEnum.QUERY)
    @PostMapping("/flowable/approves/refuseBackInfo")
    @ResponseBody
    public RespBody<String> refuseBackInfo(@RequestBody Map<String,String> params) {
        //非登陆用户不可发起申请
        SysUser user = WebUtil.currentUser();
        if(user==null){
            throw new BizException(GlobalRespCode.UNAUTHORIZED);
        }
        return RespBody.data(flowableManageService.refuseBackInfo(user,params));
    }

    /**
     * 退回到指定节点
     * @param params
     * @return
     */
    @CastleLog(operLocation = "退回到指定节点", operType = OperationTypeEnum.UPDATE)
    @PostMapping("/flowable/approves/backToNode")
    @ResponseBody
    public RespBody<String> backToNode(@RequestBody Map<String,String> params) {
        //非登陆用户不可发起申请
        SysUser user = WebUtil.currentUser();
        if(user==null){
            throw new BizException(GlobalRespCode.UNAUTHORIZED);
        }
        return RespBody.data(flowableManageService.backToNode(user,params));
    }

    /**
     * 获取所有可退回的节点
     * @param params
     * @return
     */
    @CastleLog(operLocation = "获取所有可退回的节点", operType = OperationTypeEnum.QUERY)
    @PostMapping("/flowable/approves/getAllBackNodes")
    @ResponseBody
    public RespBody<List<Map<String,Object>>> getAllBackNodes(@RequestBody Map<String,String> params){
        //非登陆用户不可发起申请
        SysUser user = WebUtil.currentUser();
        if(user==null){
            throw new BizException(GlobalRespCode.UNAUTHORIZED);
        }
        List<Map<String,Object>> list = flowableManageService.getAllBackNodes(user,params);
        return RespBody.data(list);
    }
}
